### -*- python -*-
# Copyright (C) 2003, Charles Wang.
# Author:  Charles Wang <charles@linux.net.cn>
# All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANT; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public LIcense for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

import os
import os.path
import glob
import string
import py_compile

Import('*')

### Global variable
packages_md5sum = 'result/packages.md5sum'
mlbase_files = ['result/pkgarr.py',
                mi_config.sifile,
                packages_md5sum]
pkgdirs = ' '.join(mi_config.pkgdirs.split(':'))
pkginfor_script = 'scripts/%s%sPkgInfor.py' % \
                  (string.upper(mi_config.pkgtype[0]), mi_config.pkgtype[1:])
createiso_script = 'scripts/CreateISO.py'

# packages_value - the full file info of all software packages.
packages_value = DirValue(mi_config.pkgdirs.split(':'))

### Default Build Target
# The default scons object is allisos, i.e. all iso files.
Default(env.Alias('allisos', map(mi_config.mkisofn, range(1, mi_config.max_cd_no + 1))))

use_cp_mode = mi_config.use_copy_install_mode
rpmdbtar = os.path.join(mi_config.tmpdir,'rpmdb.tar.bz2')
etctar = os.path.join(mi_config.tmpdir,'etc.tar.bz2')
cleanpkgdir = 'notclean'
if use_cp_mode:
    env.Command([rpmdbtar],
            [os.path.join(mi_config.rpmdb_dir,'.prepared')],
            ['tar -cjf $TARGET -C $rpmdb_dir/tgtsys_root .'])

    env.Command([etctar],
            ['$etctar_dir','$etctar_script'],
            ['chmod +x $etctar_script','tar -cjf $TARGET -C $etctar_dir .'])
else:
    # If we do not use the copy install mode. we should make other script clean
    # the package directory.
    cleanpkgdir = 'clean'
### Boot.iso

class BootIsoMaker(PkgMaker.StepMaker):
    target_list = [mi_config.mkisofn(1)]
    steps = ['install_miimages',
             'install_mlbasefiles',]
    if use_cp_mode:
        steps= steps + ['install_rpmdb_etctar',]
    steps+= ['add_extra_files',
             'install_bootload',
             'make_iso',
             ]

    def initenv(self):
        env = self.env

    def init_dir(self):
        cmds = ['rm -rf $bootcd_dir',
                'mkdir -p $bootcd_dir']
        return [], cmds

    def install_miimages(self):
        miimages_files = ['result/miinitrd',
                          'result/mbvmlinuz',
                          'result/mbinitrd-hd.gz']
        if mi_config.bootload == 'syslinux':
            miimages_files.extend(['result/mb' + k \
                                   for k in mi_config.kmods_arrange])
        cmds = ['mkdir -p $miimages_dir',
                'cp -u %s $miimages_dir' % \
                ' '.join(miimages_files)]

        return miimages_files, cmds

    def install_mlbasefiles(self):
        # specinfo.py is added for reference only.
        cmds = ['mkdir -p $mlbase_dir',
                'cp -u %s $mlbase_dir' % ' '.join(mlbase_files)]
        return mlbase_files, cmds

    def add_extra_files(self):
        if os.path.isdir(mi_config.addfiles_dir):
            addfiles_value = [DirValue(mi_config.addfiles_dir)]
            cmds = ['cp -a $addfiles_dir/* $bootcd_dir']
        else:
            addfiles_value = []
            cmds = []
        return addfiles_value, cmds

    def install_bootload(self):
        if mi_config.bootload == 'grub':
            bootload_files = ['MagicBooter/bootload/menu.lst',
                              'bindir/splash.xpm.gz',
                              '$devrootdir/grub/.prepared']
            cmds = ['mkdir -p $miimages_dir/grub',
                    'cp $devrootdir/grub/grub4dos-0.4.5b/chinese/grldr $miimages_dir/grub/',
                    'cp $devrootdir/grub/boot/grub/fonts $miimages_dir/grub/',
                    'cp bindir/splash.xpm.gz $miimages_dir/grub',
                    #'mv $miimages_dir/menu.lst miimages_dir/grub/',
                    'cp MagicBooter/bootload/menu.lst $bootcd_dir/',
                    ]
            return bootload_files, cmds
        else:
            return [], []

    def install_rpmdb_etctar(self):
        cmds = ['rm -r $bootcd_dir/$distname/packages/*',
                'cp %s $bootcd_dir/$distname/packages/' % rpmdbtar,
                'cp %s $bootcd_dir/$distname/packages/' % etctar,
        ]
        return [rpmdbtar, etctar], cmds

    def make_iso(self):
        cmds =['$pythonbin %s $TARGET' % createiso_script + \
               ' result/pkgarr.py $pkgdirs $bootcd_dir' + \
               ' $distname $distver 1 %s $bootload $miimages_cddir' % cleanpkgdir]
        return [createiso_script], cmds

bootiso = BootIsoMaker(env)
bootiso.make()

### Other ISOs
#iso2 - iso<max_cd_no> <- createiso_script, mlbase_files
for iso_cnt in range(2, mi_config.max_cd_no + 1):
    iso_dir = 'tmp/cd-%d' % iso_cnt
    env.Command(mi_config.mkisofn(iso_cnt),
                [createiso_script] + mlbase_files,
                ['rm -rf $iso_dir',

                 '$pythonbin %s $TARGET' % createiso_script + \
                 ' result/pkgarr.py $pkgdirs $iso_dir' + \
                 ' $distname $distver $iso_cnt %s' % cleanpkgdir
                 ],
                iso_dir = iso_dir,
                iso_cnt = iso_cnt)

### Package arrangement
# result/pkgarr.py <- scripts/PkgArrange.py, scripts/pkgpublic.py, tmp/pkginfor.py, mi_config.sifile
env.Command(['result/pkgarr.py'],
            ['scripts/PkgArrange.py',
             'scripts/pkgpublic.py',
             'tmp/pkginfor.py',
             env.Value((mi_config.volume_limit_list,
                        mi_config.placement_list,
                        mi_config.toplevel_groups,
                        mi_config.add_deps,
                        mi_config.remove_deps)),
             ],
            ['$pythonbin scripts/PkgArrange.py -o $TARGET -l tmp/pkgarr.log'])

if use_cp_mode:
    env.Command([os.path.join(mi_config.rpmdb_dir, '.prepared')],
            ['result/pkgarr.py', 'scripts/GenRpmdb.py'],
            ['sudo $pythonbin scripts/GenRpmdb.py  -t $rpmdb_dir/tgtsys_root -s $pkgdirs -p result/pkgarr.py -l $tmpdir/GenRpmdb.out.log -e $tmpdir/GenRpmdb.err.log',
             '/bin/date > $TARGET'])

# packages_md5sum <- packages_value
env.Command(packages_md5sum, packages_value,
            'find %s -name \"*.rpm\" -exec md5sum {} \; > $TARGET' % pkgdirs)

# This script must use the native python because it require rpm.
env.Command('tmp/pkginfor.py',
            [pkginfor_script, packages_value],
            ['python %s -o $TARGET -l tmp/%s.log %s' % \
             (pkginfor_script, mi_config.pkgtype, pkgdirs)])

## Skip this. Use miinitrd.cramfs as miinitrd directly.
# result/miinitrd <- result/miinitrd.cramfs
# env.Command('result/miinitrd', 'result/miinitrd.cramfs',
#             ['mkdir -p result',
#              'dd if=/dev/zero of=$TARGET bs=1M count=%d' % mi_config.EXT2FSSIZE,
#              '/sbin/mke2fs -F $TARGET',
#              'mkdir -p tmp/miinitrd.mnt',
#              'mount -o loop $TARGET tmp/miinitrd.mnt',
#              'cp $SOURCE tmp/miinitrd.mnt',
#              'umount $TARGET'])

### miinitrd
# result/miinitrd <- bindir/root.step1.tar.gz, bindir/root.src.tar.gz, bindir/kmodules-x.xx.xx.tar-bz2
#                    <specdir>/post_install.sh
class MiinitrdMaker(PkgMaker.StepMaker):
    target_list = ['result/miinitrd']
    ROOT = 'tmp/root.initrd'
    steps = ['init_dir',
             'extract_bins',
             'copy_bootload',
             'install_configfiles',
             'install_tranlatefiles',]
    if use_cp_mode:
        steps = steps + ['install_cpinstmode_UIxml',]
    steps+= ['install_post',
             'mkcramfs'
             ]

    def init_dir(self):
        cmds = ['rm -rf $ROOT',
                'mkdir -p $ROOT']
        return [], cmds

    def extract_bins(self):
        toextract = ['bindir/root.step1.tar.gz',
                     'bindir/root.src.tar.gz',
                     'bindir/kmodules-${mikernelver}.tar.bz2']
        #if mi_config.useudev:
        #    toextract.append('bindir/udev-${udev_version}.tar.bz2')
        mkstep2_script = 'scripts/mkstep2.py'
        cmds = ['$pythonbin %s $udev_arg %s' % \
                (mkstep2_script,
                 ' '.join(toextract))]
        return toextract + [mkstep2_script], cmds

    def copy_bootload(self):
        env = self.env
        if mi_config.bootload == 'grub':
            # extract grub for dos
            cmds = ['cp $devrootdir/grub/grub4dos-0.4.5b/chinese/grldr' +
                    ' $ROOT/usr/share/']

            env.Command('$devrootdir/grub/.prepared',
                        ['bindir/grub4dos-0.4.5b-2010-05-31.zip',
                         'bindir/boot_fdr.zip'],
                        ['rm -rf $devrootdir/grub',
                         'mkdir -p $devrootdir/grub',
                         self.get_extract_cmd('bindir/grub4dos-0.4.5b-2010-05-31.zip',
                                              '$devrootdir/grub'),
                         self.get_extract_cmd('bindir/boot_fdr.zip',
                                              '$devrootdir/grub'),
                         'ls -l $SOURCE > $TARGET'])

            return ['$devrootdir/grub/.prepared'], cmds

        else:
            return [], []

    def install_configfiles(self):
        configfiles = [('src/magic.installer/mipublic.py',
                        '$ROOT/$pythondir/site-packages/'),

                       ('src/magic.installer/magic.autopart.xml',
                        '$ROOT/usr/share/MagicInstaller/')]
        slist = []
        cmds = []
        for src, dest in configfiles:
            slist.append(src)
            cmds.extend(['mkdir -p %s' % dest,
                         'cp -a %s %s' % (src, dest)])
        return slist, cmds

    def install_tranlatefiles(self):
        slist = []
        cmds = []
        for lang in mi_config.all_linguas:
            inst_file = 'src/magic.installer/po/%s.mo' % lang
            dest_file = '$ROOT/usr/share/locale/%s/LC_MESSAGES/${textdomain}.mo' % lang
            slist.append(inst_file)
            cmds.extend(['mkdir -p %s' % os.path.dirname(dest_file),
                         'cp -a %s %s' % (inst_file, dest_file)])
        return slist, cmds

    def install_cpinstmode_UIxml(self):
        slist = []
        cmds = []
        inst_file = 'src/magic.installer/UIxml/takeactions.xml.cpinstmode'
        dest_file = '$ROOT$root_datadir/UIxml/takeactions.xml'
        slist.append(inst_file)
        cmds.extend(['mkdir -p %s' % os.path.dirname(dest_file),
                         'cp -a %s %s' % (inst_file, dest_file)])
        return slist, cmds

    def install_post(self):
        env = self.env
        post_script = '$specdir/post_install.sh'
        if os.path.exists(env.subst(post_script)):
            cmds = ['cp %s $ROOT/root' % post_script,
                    'chmod 700 $ROOT/root/post_install.sh']
            return [post_script], cmds
        else:
            return [], []

    def mkcramfs(self):
        cmds = ['mkdir -p result',
                '/sbin/mkfs.cramfs $ROOT $TARGET']
        return [], cmds

miinitrd = MiinitrdMaker(env)
miinitrd.make()

if mi_config.develmode:
    ## tmp/root.step1.tar.gz <- mkstep1.py, use mkstep1.py to install necessary supporting files from ./bindir
    #env.Command('tmp/root.step1.tar.gz', 'scripts/mkstep1.py',
    #            ['$pythonbin scripts/mkstep1.py $mkstep_arg',
    #                'tar c -C tmp/root.step1 . | gzip -9 > $TARGET'])
    #env.Depends('tmp/root.step1.tar.gz',
    #            glob.glob('scripts/pystep1/*.py') + ['scripts/pystep1/mi_core.py'])
    ##env.Depends('tmp/root.step1.tar.gz', 'bindir/kmodules-%s.tar.bz2' % mi_config.mikernelver)
    #env.Command('scripts/pystep1/mi_core.py', 'scripts/pystep1/mi_core.py.m4',
    #            'm4 -DPYTHONDIR="$pythondir" -DBBVER="$busybox_version" $SOURCE > $TARGET')

    env.Command('bindir/root.src.tar.gz', env.Alias('root_src'),
                ['tar c -C $destdir . | gzip -9 > $TARGET'])

### Hotfix file
# Handle with hotfix file
hotfix_path = mi_config.hotfixfiles_dir
if glob.glob(hotfix_path + '/*'):
    Default(env.Command('%s.hotfix' % mi_config.mkisofn(1),
                        DirValue(hotfix_path),
                        ['(cd $SOURCE && find . -print | cpio -o -H newc | gzip -9) > $TARGET']))
else:
    Delete('%s.hotfix' % mi_config.mkisofn(1))

### SConscript
SConscript('src/SConscript')
